package org.raymond.iworks.study.spring.service;

import lombok.extern.slf4j.Slf4j;
import org.raymond.iworks.study.spring.service.BaseTestService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

/**
 * @author raymond
 * @version V1.0
 * @Description: TODO
 */
@Slf4j
@Service
public class PropagationService {
    @Autowired
    private BaseTestService baseTestService;

    // REQUIRED: 强制执行物理事务,如果还没有事务存在,则在当前范围本地执行,或者参与为更大范围定义的现有“外部”事务.
    // 没有事务新建事务,有事务则加入事务
    @Transactional(propagation= Propagation.REQUIRED, rollbackFor = Exception.class)
    public void propagationRequiredTestA() throws Exception {
        // a加入事务t1
        baseTestService.requiredTest(false);
        // b加入事务t1, b内部抛出异常,异常向上继续抛出,a,b,都在同一个事务t1下,都回滚, pass
        baseTestService.requiredTest(true);
    }

    @Transactional(propagation= Propagation.REQUIRED, rollbackFor = Exception.class)
    public void propagationRequiredTestB() throws Exception {
        // a加入事务t1
        baseTestService.requiredTest(false);
        try {
            // b加入事务t1, b内部抛出异常,但被catch住,b内部尝试回滚t1,a尝试提交t1,则报rollback-only错, pass
            baseTestService.requiredTest(true);
        }catch (Exception e){
            log.error("{}", e.getMessage());
        }
    }

    // REQUIRED_NEW: 没有事务新建事务,有事务也新建事务
    @Transactional(propagation= Propagation.REQUIRED, rollbackFor = Exception.class)
    public void propagationRequiredNewTestA() throws Exception {
        // a加入事务t1
        baseTestService.requiredTest(false);
        // b新建事务t2
        baseTestService.requiredNewTest(false);
        // c新建事务t3
        baseTestService.requiredNewTest(true);
        // C内部抛出异常,c与a,b是不同的事务,但是异常会上升,外面也会抛出异常,因此a,c两个事务都有异常,都要回滚,b没有异常,正常提交,pass
    }
    @Transactional(propagation= Propagation.REQUIRED, rollbackFor = Exception.class)
    public void propagationRequiredNewTestB() throws Exception {
        // a加入事务t1
        baseTestService.requiredTest(false);
        // b新建事务t2
        baseTestService.requiredNewTest(false);
        // c新建事务t3
        try {
            baseTestService.requiredNewTest(true);
        }catch(Exception e){
            log.error("{}", e.getMessage());
        }
        // C内部抛出异常,但被catch住, 异常不再上升,因此a,b正常提交,c回滚,pass
    }

    // NESTED: 没有事务新建事务,有事务则新建嵌套子事务
    @Transactional(propagation= Propagation.REQUIRED, rollbackFor = Exception.class)
    public void propagationNestedTestA() throws Exception {
        // a加入事务t1
        baseTestService.requiredTest(false);
        // b新建嵌套子事务t2
        baseTestService.nestedTest(false);
        // c新建嵌套子事务t3
        baseTestService.nestedTest(true);
        // C内部抛出异常,异常上升,父事务t1回滚,子事务t3本身抛出异常要回滚,子事务t2从属于父事务t1,受其影响也要回滚,pass
    }
    @Transactional(propagation= Propagation.REQUIRED, rollbackFor = Exception.class)
    public void propagationNestedTestB() throws Exception {
        // a加入事务t1
        baseTestService.requiredTest(false);
        // b新建嵌套子事务t2
        baseTestService.nestedTest(false);
        // c新建嵌套子事务t3
        try {
            baseTestService.nestedTest(true);
        }catch(Exception e){
            log.error("{}", e.getMessage());
        }
        // C内部抛出异常,异常被catch,父事务t1不回滚,子事务t3本身抛出异常要回滚,子事务t2从属于父事务t1,也不回滚,pass
    }
    // SUPPORTS: 没有事务以非事务执行,有事务则加入事务
    public void propagationSupportsTestA() throws Exception {
        // 非事务执行
        baseTestService.supportsTest(false);
        baseTestService.supportsTest(true);
        // 内部抛出异常,无事务,不回滚,pass
    }
    @Transactional(propagation= Propagation.REQUIRED, rollbackFor = Exception.class)
    public void propagationSupportsTestB() throws Exception {
        // 加入事务t1
        baseTestService.supportsTest(false);
        // 加入事务t1
        baseTestService.supportsTest(true);
        // 内部抛出异常,有事务,同一个事务,全部回滚, pass
    }
    // NOT_SUPPORTED: 没有事务以非事务执行,有事务则挂起当前事务以非事务执行
    public void propagationNotSupportedTestA() throws Exception {
        // 非事务执行
        baseTestService.notSupportedTest(false);
        baseTestService.notSupportedTest(true);
        // 内部抛出异常,无事务,不回滚,pass
    }
    @Transactional(propagation= Propagation.REQUIRED, rollbackFor = Exception.class)
    public void propagationNotSupportedTestB() throws Exception {
        // 事务t1挂起,内部以非事务执行
        baseTestService.notSupportedTest(false);
        // 事务t1挂起,内部以非事务执行
        baseTestService.notSupportedTest(true);
        // 内部抛出异常,无事务,不回滚,pass
    }
    // NEVER: 没有事务以非事务执行,有事务则报错
    public void propagationNeverTestA() throws Exception {
        // 非事务执行
        baseTestService.neverTest(false);
        baseTestService.neverTest(true);
        // 内部抛出异常,无事务,不回滚, pass
    }
    @Transactional(propagation= Propagation.REQUIRED, rollbackFor = Exception.class)
    public void propagationNeverTestB() throws Exception {
        // 有事务,报错, pass
        baseTestService.neverTest(false);
    }
    // MANDATORY: 没有事务就报错,有事务则加入事务
    public void propagationMandatoryTestA() throws Exception {
        // 没有事务,报错, pass
        baseTestService.mandatoryTest(false);
    }
    @Transactional(propagation= Propagation.REQUIRED, rollbackFor = Exception.class)
    public void propagationMandatoryTestB() throws Exception {
        // 加入事务t1
        baseTestService.mandatoryTest(false);
        // 加入事务t1
        baseTestService.mandatoryTest(true);
        // 内部抛出异常,有同一个事务,全部回滚, pass
    }
}
